using System.Collections.Generic;
using System.Windows.Forms;
using Lizk.SimpleHUD;
using System.IO;
using System;
using System.Drawing;
using Lizk.Utilities;

namespace SharpMedia.Input
{
    public delegate void CommandEvent(object sender, HUDCommands command);

    /// <summary>
    /// Fires HUDCommands
    /// </summary>
    public class FormInputController
    {
        private List<InputCommand> commands = new List<InputCommand>();
        private Form form;

        private string configFile;

        public event EventHandler<CommandEventArgs> FireCommand;

        public string ConfigFile
        {
            get { return configFile; }
            set { configFile = value; }
        }

        public FormInputController(string configFile, Form form)
        {
            this.configFile = configFile;
            this.form = form;
            form.KeyDown += new KeyEventHandler(KeyDown);
            form.MouseClick += new MouseEventHandler(MouseClick);
            form.MouseWheel += new MouseEventHandler(MouseWheel);
            form.KeyPress += new KeyPressEventHandler(form_KeyPress);
            InitializeCommands();
        }


        void form_KeyPress(object sender, KeyPressEventArgs e)
        {
            foreach(InputCommand command in commands) 
            {
                if (command.Command == HUDCommands.Select && command.Key == e.KeyChar)
                    return;
                if (command.Command == HUDCommands.Back && command.Key == e.KeyChar)
                    return;
            }

            if (Form.ActiveForm == form && FireCommand != null)
            {
                FireCommand(this, new CommandEventArgs(HUDCommands.KeyPress, e.KeyChar));
                e.Handled = true;
            }
        }


        private void InitializeCommands()
        {
            if(File.Exists(configFile)) {
                try
                {
                    commands = XmlSettings.loadXml<List<InputCommand>>(configFile);
                    return;
                }
                catch { }
            } else {

            commands.Add(new KeyboardCommand(Keys.Up, Keys.None, HUDCommands.Up));
                commands.Add(new KeyboardCommand(Keys.Down, Keys.None, HUDCommands.Down));
                commands.Add(new KeyboardCommand(Keys.Left, Keys.None, HUDCommands.Left));
                commands.Add(new KeyboardCommand(Keys.Right, Keys.None, HUDCommands.Right));
                commands.Add(new KeyboardCommand(Keys.Back, Keys.None, HUDCommands.Back));
                commands.Add(new KeyboardCommand(Keys.Enter, Keys.Alt, HUDCommands.Fullscreen));
                commands.Add(new KeyboardCommand(Keys.Enter, Keys.None, HUDCommands.Select));
                commands.Add(new KeyboardCommand(Keys.Next, Keys.None, HUDCommands.PageDown));
                commands.Add(new KeyboardCommand(Keys.Prior, Keys.None, HUDCommands.PageUp));
                commands.Add(new KeyboardCommand(Keys.Space, Keys.None, HUDCommands.Menu));
                commands.Add(new KeyboardCommand(Keys.F9, Keys.None, HUDCommands.UpdateDatabase));
                commands.Add(new KeyboardCommand(Keys.F11, Keys.None, HUDCommands.Web));
                commands.Add(new KeyboardCommand(Keys.F1, Keys.None, HUDCommands.Preset1));
                commands.Add(new KeyboardCommand(Keys.F2, Keys.None, HUDCommands.Preset2));
                commands.Add(new KeyboardCommand(Keys.F3, Keys.None, HUDCommands.Preset3));
                commands.Add(new KeyboardCommand(Keys.MediaPlayPause, Keys.None, HUDCommands.PlayPause));
                commands.Add(new KeyboardCommand(Keys.MediaStop, Keys.None, HUDCommands.Stop));
                commands.Add(new KeyboardCommand(Keys.MediaPreviousTrack, Keys.None, HUDCommands.Previous));
                commands.Add(new KeyboardCommand(Keys.MediaNextTrack, Keys.None, HUDCommands.Next));
                commands.Add(new KeyboardCommand(Keys.Left, Keys.None, HUDCommands.Rewind));
                commands.Add(new KeyboardCommand(Keys.Right, Keys.None, HUDCommands.Forward));
                commands.Add(new MouseWheelCommand(true, HUDCommands.Up));
                commands.Add(new MouseWheelCommand(false, HUDCommands.Down));
            }
            XmlSettings.saveXml(commands, configFile);
        }


        private void KeyDown(object sender, KeyEventArgs e)
        {
            if(Form.ActiveForm == form)
            foreach (InputCommand kc in commands)
                if (kc is KeyboardCommand && ((KeyboardCommand)kc).KeyboardKey == e.KeyCode && e.Modifiers  == ((KeyboardCommand)kc).Modifiers)
                {
                    if (FireCommand != null)
                    {
                        FireCommand(this, new CommandEventArgs(kc.Command));
                        e.Handled = true;
                    }
                    break;
                }
        }
        private void MouseClick(object sender, MouseEventArgs e)
        {
            
            if (Form.ActiveForm == form)
                foreach (InputCommand mc in commands)
                if (mc is MouseCommand && ((MouseCommand)mc).Button == e.Button)
                {
                    if (FireCommand != null)
                        FireCommand(this, new CommandEventArgs(mc.Command));
                    break;
                }
        }

        private void MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0 && Form.ActiveForm == form)
                foreach (InputCommand mc in commands)
                    if (mc is MouseWheelCommand && ((MouseWheelCommand)mc).Up)
                    {
                        if (FireCommand != null)
                            FireCommand(this, new CommandEventArgs(mc.Command));
                        return;
                    }


            if (e.Delta < 0 && Form.ActiveForm == form)
                foreach (InputCommand mc in commands)
                    if (mc is MouseWheelCommand && !((MouseWheelCommand)mc).Up)
                    {
                        if (FireCommand != null)
                            FireCommand(this, new CommandEventArgs(mc.Command));
                        return;
                    }
        }
    
    
    }

}
